package net.zoneland.knowledge.service.impl;

import java.text.MessageFormat;
import java.util.*;
import java.util.stream.Collectors;

import org.apache.commons.collections.CollectionUtils;
import org.apache.commons.lang.ArrayUtils;
import org.apache.commons.lang.StringUtils;
import org.joda.time.DateTime;
import org.joda.time.LocalDateTime;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.web.util.UriComponentsBuilder;

import com.google.common.base.Preconditions;

import net.zoneland.knowledge.cache.RedisCacheUtil;
import net.zoneland.knowledge.config.TalkConfig;
import net.zoneland.knowledge.constant.ApproveConstant;
import net.zoneland.knowledge.constant.BizConstant;
import net.zoneland.knowledge.constant.Constants;
import net.zoneland.knowledge.dao.WorkApplyInfoMapper;
import net.zoneland.knowledge.enums.WorkStatusEnum;
import net.zoneland.knowledge.exceptions.WorkApplyException;
import net.zoneland.knowledge.model.LoginUserPojo;
import net.zoneland.knowledge.model.WorkApplyInfo;
import net.zoneland.knowledge.model.WorkApplyInfoAttachment;
import net.zoneland.knowledge.model.WorkApproveOpinion;
import net.zoneland.knowledge.service.ChapterApplyInfoService;
import net.zoneland.knowledge.service.EmailService;
import net.zoneland.knowledge.service.NotifyService;
import net.zoneland.knowledge.service.RoleService;
import net.zoneland.knowledge.service.UniFlowService;
import net.zoneland.knowledge.service.WorkApplyInfoService;
import net.zoneland.knowledge.service.WorkDoneStatusInfoService;
import net.zoneland.knowledge.service.bean.ResultInfo;
import net.zoneland.knowledge.utils.BizCacheUtils;
import net.zoneland.knowledge.utils.WorkApplyOperationUtils;
import net.zoneland.uniflow.client.DecisionObject;
import net.zoneland.uniflow.client.TaskObject;
import net.zoneland.uniflow.client.UserInfo;

/**
 * 用印申请service实现.
 * @author bcc
 */
@Service
public class ChapterApplyInfoServiceImpl implements ChapterApplyInfoService {
    /**
     * 日志.
     */
    private static final Logger LOGGER = LoggerFactory.getLogger(ChapterApplyInfoServiceImpl.class);
    /**
     * 流程业务接口.
     */
    @Autowired
    private UniFlowService uniFlowService;

    @Autowired
    private WorkApplyInfoService workApplyInfoService;

    /**
     * 工单信息数据接口.
     */
    @Autowired
    private WorkApplyInfoMapper workApplyInfoMapper;

    @Autowired
    private NotifyService notifyService;

    @Autowired
    private TalkConfig talkConfig;

    @Autowired
    private EmailService<TaskObject[], WorkApplyInfo> emailService;

    /**
     * 用户角色信息相关接口.
     */
    @Autowired
    private RoleService roleService;

    /**
     * redis缓存工具类.
     */
    @Autowired
    private RedisCacheUtil redisCacheUtil;

    /**
     * 已办状态表服务.
     */
    @Autowired
    private WorkDoneStatusInfoService workDoneStatusInfoService;

    @Override
    public void saveDraft(final WorkApplyInfo info, final LoginUserPojo user) {

        try {
            Preconditions.checkNotNull(info, "当前工单信息不能为空！");
            if (StringUtils.isBlank(info.getId())) {
                insertChapterApply(info, user);
            } else {
                updateChapterApply(info);
            }
            // 起草保存也要更新当前工单状态，但不需要加已办记录，这个要特殊处理
            workDoneStatusInfoService.saveDraftWorkApplyDoneStatus(info, user);
        } catch (final Exception e) {
            throw new WorkApplyException("保存工单失败", e);
        }
    }

    /**
     * 提交草稿工单.
     *
     * @param info 工单信息
     * @param taskId 任务id
     * @param opinion 意见
     * @param user 当前用户
     */
    @Override
    @Transactional(rollbackFor = Exception.class)
    public void submitDraft(final WorkApplyInfo info, final String taskId,
                            final String opinion, final LoginUserPojo user) {
        try {
            Preconditions.checkNotNull(info, "工单信息不能为空！");
            Preconditions.checkNotNull(user, "操作用户不能为空！");
            Preconditions.checkArgument(StringUtils.isBlank(info.getCreatorUid())
                            || StringUtils.equals(user.getUserID(), info.getCreatorUid()),
                    "当前用户不是工单发起人！");
            Preconditions.checkArgument(info.getStatus() == null
                    || info.getStatus() == WorkStatusEnum.DRAFT, "当前工单非草稿状态，不能执行提交草稿工单！");
            Preconditions.checkArgument(info.getStatus() == null || info.getStatus() == WorkStatusEnum.DRAFT,
                    "当前工单状态非草稿，不能提交！");
            info.setCreatorPartyOrgUuid(user.getPartyOrgUuid());

            // 获取用章申请流程在拟稿节点的下一个任务状态
            final WorkStatusEnum workStatus = WorkStatusEnum.getChapterDraftNextStatus(info.getUseSealType());
            final UserInfo statusHandler = workStatus.getHandler(info);
            Preconditions.checkArgument(Objects.nonNull(statusHandler), "未找到下个节点的审批人");
            info.setHandlerUid(statusHandler.getUserId());
            info.setHandlerName(statusHandler.getUserName());
            info.setStatus(workStatus);
            //先保存工单
            this.saveDraft(info, user);
            // 流程扩展参数设置
            Map<String, String> extendData = new HashMap<>();
            extendData.put("useSealType", info.getUseSealType());
            workApplyInfoMapper.insertWorkApproveOpinion(WorkApplyOperationUtils.buildApproveOpinionWithNodeId(opinion,
                                                                                                               user, info,
                                                                                            ApproveConstant.DEFAULT_SUBMIT_NAME,
                                                                                            WorkStatusEnum.DRAFT.getValue()));
            String taskIdTmp;
            final TaskObject[] tasks = WorkApplyOperationUtils.queryTask(uniFlowService, user.getUserID(), info,
                                                                         new String[]{WorkStatusEnum.DRAFT.getValue()},
                                                                         WorkApplyOperationUtils.READY_STATUS);
            taskIdTmp = ArrayUtils.isNotEmpty(tasks) ? tasks[0].getTiid() : null;
            ResultInfo resultInfo;
            if (StringUtils.isNotBlank(taskIdTmp)) {
                // 有可能是退回拟稿后再次提交，这时需要调用完成任务
                resultInfo = uniFlowService.completeTask(taskIdTmp, WorkApplyOperationUtils.convertUserInfo(user),
                                                         DecisionObject.DECISION_SUBMIT, ApproveConstant.DEFAULT_SUBMIT_NAME,
                                                         null, workStatus.getValue(),
                                                         new UserInfo[]{statusHandler},
                    extendData, null);
            } else {
                resultInfo = uniFlowService.startAndJumpTask(BizConstant.CHAPTER_APPLY_PROCESS_CODE,
                                                             new UserInfo(user.getUserID(), user.getUserName()),
                                                             info.getId(),
                                                             info.getTitle(), workStatus.getValue(),
                                                             new UserInfo[]{statusHandler}, extendData);
            }
            Preconditions.checkNotNull(resultInfo, ApproveConstant.DRAFT_ERROR_MESSAGE);
            Preconditions.checkArgument(resultInfo.isResult(), resultInfo.getInfo());
            // 用印时间
            if (info.getChapterDate() == null) {
                info.setChapterDate(DateTime.now().toDate());
            }
            workDoneStatusInfoService.dealChapterApplyDoneStatus(info, user);
            workApplyInfoMapper.updateWorkApplyInfo(info);
            emailService.sendEmail(this::sendEmailFunction, (TaskObject[]) resultInfo.getData(), info);
        } catch (final Exception e) {
            throw new WorkApplyException("提交草稿工单失败！taskId:" + taskId, e);
        }
    }


    @Override
    public void submit(final String taskId, final WorkApplyInfo info,  final String opinion, final LoginUserPojo user) {

        try {
            Preconditions.checkArgument(StringUtils.isNotBlank(taskId), WorkApplyInfoService.TASK_ID_BLANK_ERROR_MSG);
            Preconditions.checkArgument(StringUtils.isNotBlank(info.getHandlerUid())
                                        && StringUtils.equals(user.getUserID(), info.getHandlerUid()),
                                        "当前用户不是工单处理人！");
            info.setUpdateTime(DateTime.now().toDate());
            final WorkStatusEnum currentStatus = info.getStatus();
            final WorkStatusEnum nextSubmitStatus = currentStatus.getNextSubmitStatus(info.getUseSealType());
            final UserInfo nextHandler = nextSubmitStatus.getHandler(info);
            UserInfo[] nextHandlers = null;
            if (null != nextHandler) {
                info.setHandlerUid(nextHandler.getUserId());
                info.setHandlerName(nextHandler.getUserName());
                nextHandlers = new UserInfo[]{nextHandler};
            } else {
                info.setHandlerUid(null);
                info.setHandlerName(null);
            }
            info.setDispatched(CollectionUtils.isNotEmpty(info.getSubTasks()));
            info.setStatus(nextSubmitStatus);
            this.workApplyInfoMapper.updateWorkApplyInfo(info);
            final WorkApproveOpinion workApproveOpinion = WorkApplyOperationUtils.buildApproveOpinionWithNodeId(opinion, user,
                                                                                                    info, "同意",
                                                                                                    currentStatus.getValue());
            this.workApplyInfoMapper.insertWorkApproveOpinion(workApproveOpinion);
            final ResultInfo resultInfo = this.uniFlowService.completeTask(taskId, WorkApplyOperationUtils.convertUserInfo(user),
                                                                           DecisionObject.DECISION_SUBMIT,
                                                                           ApproveConstant.DEFAULT_SUBMIT_NAME,
                                                                           null, null, nextHandlers, null, null);
            Preconditions.checkNotNull(resultInfo, ApproveConstant.DRAFT_ERROR_MESSAGE);
            Preconditions.checkArgument(resultInfo.isResult(), resultInfo.getInfo());
            workDoneStatusInfoService.dealChapterApplyDoneStatus(info, user);
            //如果审批结束需要发送邮件给发起人
            if (nextSubmitStatus == WorkStatusEnum.END) {
                emailService.sendEmail(this::sendFinishEmailFunction, (TaskObject[]) resultInfo.getData(), info);
                // 发送给印章管理员
                Set<String> managers = getManager();
                if(CollectionUtils.isNotEmpty(managers)) {
                    emailService.sendEmail(this::sendFinishEmailToManagerFunction,
                        (TaskObject[]) resultInfo.getData(), info, Constants.ROLE_CHAPTER_ADMIN,  managers.toArray(new String[managers.size()]));
                }
            } else {
                emailService.sendEmail(this::sendEmailFunction, (TaskObject[]) resultInfo.getData(), info);
            }
        } catch (final Exception e) {
            LOGGER.error("submit error taskId:{}", taskId, e);
            throw new WorkApplyException("提交工单失败！" + e.getMessage() + "taskId:" + taskId, e);
        }
    }


    @Override
    @Transactional(rollbackFor = Exception.class)
    public void chapterReject(final String workApplyId, final String taskId, final String rejectReason,
                              final LoginUserPojo user) {
        try {
            Preconditions.checkArgument(StringUtils.isNotBlank(taskId), WorkApplyInfoService.TASK_ID_BLANK_ERROR_MSG);
            Preconditions.checkArgument(StringUtils.isNotBlank(rejectReason), "退回原因不能为空！");
            final WorkApplyInfo info = workApplyInfoService.findWorkApplyInfoById(workApplyId);
            Preconditions.checkArgument(StringUtils.isNotBlank(info.getHandlerUid())
                                        && StringUtils.equals(user.getUserID(), info.getHandlerUid()),
                                        "当前用户不是工单处理人！");

            final WorkStatusEnum currentStatus = info.getStatus();
            final WorkStatusEnum rejectStatus = info.getStatus().getRejectStatus(info.getUseSealType());
            final UserInfo handler = rejectStatus.getHandler(info);
            info.setHandlerUid(handler.getUserId());
            info.setHandlerName(handler.getUserName());
            info.setUpdateTime(DateTime.now().toDate());
            info.setStatus(rejectStatus);
            this.workApplyInfoMapper.updateWorkApplyInfo(info);
            final WorkApproveOpinion option = WorkApplyOperationUtils.buildApproveOpinionWithNodeId(rejectReason, user,
                                                                                    info, ApproveConstant.DEFAULT_REJECT_NAME,
                                                                                                    currentStatus.getValue());
            this.workApplyInfoMapper.insertWorkApproveOpinion(option);
            final ResultInfo res = uniFlowService.completeTask(taskId, new UserInfo(user.getUserID(), user.getUserName()),
                                                               DecisionObject.DECISION_NO, ApproveConstant.DEFAULT_REJECT_NAME,
                                                               rejectReason, rejectStatus.getValue(),
                                                               new UserInfo[]{handler}, null, null);
            Preconditions.checkArgument(res != null && res.isResult(), "退回工单失败！");
            workDoneStatusInfoService.dealChapterApplyDoneStatus(info, user);
            emailService.sendEmail(this::sendEmailFunction, (TaskObject[]) res.getData(), info);
        } catch (final Exception e) {
            LOGGER.error("reject error workApplyId:{}, taskId:{}", workApplyId, taskId, e);
            throw new WorkApplyException("退回工单失败!" + e.getMessage() + "工单id:" + workApplyId + ", taskId:" + taskId, e);
        }
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public void backToDraft(final String workApplyId, final String taskId, final String rejectReason, final LoginUserPojo user) {

        try {
            Preconditions.checkArgument(StringUtils.isNotBlank(taskId), WorkApplyInfoService.TASK_ID_BLANK_ERROR_MSG);
            Preconditions.checkArgument(StringUtils.isNotBlank(rejectReason), "退回原因不能为空！");
            final WorkApplyInfo info = workApplyInfoService.findWorkApplyInfoById(workApplyId);
            Preconditions.checkArgument(StringUtils.isNotBlank(info.getHandlerUid())
                                        && StringUtils.equals(user.getUserID(), info.getHandlerUid()),
                                        "当前用户不是工单处理人！");
            final WorkStatusEnum currentStatus = info.getStatus();
            final WorkStatusEnum rejectStatus = WorkStatusEnum.DRAFT;
            final UserInfo handler = rejectStatus.getHandler(info);
            info.setHandlerUid(handler.getUserId());
            info.setHandlerName(handler.getUserName());
            info.setUpdateTime(DateTime.now().toDate());
            info.setStatus(rejectStatus);
            this.workApplyInfoMapper.updateWorkApplyInfo(info);
            final WorkApproveOpinion option = WorkApplyOperationUtils.buildApproveOpinionWithNodeId(rejectReason, user,
                                                                                                    info, "退回至干事",
                                                                                                    currentStatus.getValue());
            this.workApplyInfoMapper.insertWorkApproveOpinion(option);
            final ResultInfo res = uniFlowService.completeTask(taskId, new UserInfo(user.getUserID(), user.getUserName()),
                                                               DecisionObject.DECISION_JUMP, "退回至干事",
                                                               rejectReason, rejectStatus.getValue(),
                                                               new UserInfo[]{handler}, null, null);
            Preconditions.checkArgument(res != null && res.isResult(), "退回工单失败！");
            workDoneStatusInfoService.dealChapterApplyDoneStatus(info, user);
            emailService.sendEmail(this::sendEmailFunction, (TaskObject[]) res.getData(), info);
        } catch (final Exception e) {
            LOGGER.error("backToDraft error workApplyId:{}, taskId:{}", workApplyId, taskId, e);
            throw new WorkApplyException("退回到起草失败!" + e.getMessage() + "工单id:" + workApplyId + ", taskId:" + taskId, e);
        }
    }


    private void updateChapterApply(final WorkApplyInfo info) {

        final WorkApplyInfo oldApplyInfo = workApplyInfoService.findWorkApplyInfoById(info.getId());
        Preconditions.checkNotNull(oldApplyInfo, "待更新工单不存在！");
        info.setUpdateTime(DateTime.now().toDate());
        workApplyInfoMapper.updateWorkApplyInfo(info);
        //附件附件更新
        updateAttachments(info, oldApplyInfo);
    }

    private void updateAttachments(final WorkApplyInfo info, final WorkApplyInfo oldApplyInfo) {
        // 参考附件更新
        if (CollectionUtils.isNotEmpty(info.getAttachments())) {
            final List<WorkApplyInfoAttachment> newInsertAttaches = info.getAttachments()
                .stream()
                .filter(it -> StringUtils.isBlank(it.getId()))
                .collect(Collectors.toList());
            for (final WorkApplyInfoAttachment attachment : newInsertAttaches) {
                attachment.setId(UUID.randomUUID()
                                     .toString());
                attachment.setWorkApplyId(info.getId());
                workApplyInfoMapper.insertWorkApplyInfoAttachment(attachment);
            }
        }
        // 参考附件检查删除
        final List<WorkApplyInfoAttachment> oldAttaches = oldApplyInfo.getAttachments();
        if (CollectionUtils.isNotEmpty(oldAttaches)) {
            final Set<String> subAttachmentIds = Optional.ofNullable(info.getAttachments())
                .map(it -> it.stream()
                    .map(WorkApplyInfoAttachment::getId)
                    .collect(Collectors.toSet()))
                .orElseGet(Collections::emptySet);
            oldAttaches.stream()
                .filter(it -> !subAttachmentIds.contains(it.getId()))
                .forEach(x -> workApplyInfoMapper.deleteAttachmentById(x.getId()));
        }
    }

    /**
     * 插入工单.
     *
     * @param chapterApplyInfo 工单
     * @param user             当前用户
     */
    private void insertChapterApply(final WorkApplyInfo chapterApplyInfo, final LoginUserPojo user) {

        chapterApplyInfo.setId(UUID.randomUUID().toString());
        final Date now = DateTime.now().toDate();
        if (chapterApplyInfo.getCreateTime() == null) {
            chapterApplyInfo.setCreateTime(now);
        }
        chapterApplyInfo.setMainWorkApplyId(chapterApplyInfo.getId());
        chapterApplyInfo.setApplyId(chapterApplyInfo.getId());
        chapterApplyInfo.setUpdateTime(now);
        chapterApplyInfo.setCreatorUid(user.getUserID());
        chapterApplyInfo.setCreatorName(user.getUserName());
        if (chapterApplyInfo.getStatus() == null) {
            chapterApplyInfo.setStatus(WorkStatusEnum.DRAFT);
        }

        workApplyInfoMapper.insertWorkApplyInfo(chapterApplyInfo);
        insertDraftAttachments(chapterApplyInfo);
        if (CollectionUtils.isNotEmpty(chapterApplyInfo.getWorkApproveOpinions())) {
            for (final WorkApproveOpinion opinion : chapterApplyInfo.getWorkApproveOpinions()) {
                opinion.setId(UUID.randomUUID().toString());
                opinion.setWorkApplyId(chapterApplyInfo.getId());
                if (opinion.getApproveTime() == null) {
                    opinion.setApproveTime(now);
                }
                workApplyInfoMapper.insertWorkApproveOpinion(opinion);
            }
        }
    }

    private void insertDraftAttachments(final WorkApplyInfo chapterApplyInfo) {

        if (CollectionUtils.isNotEmpty(chapterApplyInfo.getAttachments())) {
            for (final WorkApplyInfoAttachment attachment : chapterApplyInfo.getAttachments()) {
                attachment.setId(UUID.randomUUID()
                                     .toString());
                attachment.setWorkApplyId(chapterApplyInfo.getId());
                workApplyInfoMapper.insertWorkApplyInfoAttachment(attachment);
            }
        }
    }

    /**
     * 邮件发送.
     * 格式
     * 标题：党建机器人-用章申请流程：工单标题
     * 内容：
     * 请处理党建机器人-用章申请流程任务工单：工单标题。
     * 发起人：张三
     * 发起时间：2022-09-30 10:33
     * @param map 邮件相关参数
     *            key emailLeader: 邮件接收者
     *            key param: uniflow TaskObject
     *            key workApplyInfo:工单实例
     */
    private void sendEmailFunction(final Map<String, Object> map) {
        final String titleTemplate = "党建机器人-用章申请流程：{0}";
        final String contentTemplate = "<a href=\"{0}\">请处理党建机器人-用章申请流程任务工单:{1}</a>"
                         + "<br/>发起人：{2}"
                         + "<br/>发起时间：{3}";
        emailService.sendEmailFunction(titleTemplate,contentTemplate,BizConstant.CHAPTER_APPLY_PROCESS_CODE,talkConfig.getSiteUrl(),map);
    }

    /**
     * 构建审批结束发送邮件.
     * @param map 参数.
     */
    private void sendFinishEmailFunction(final Map<String, Object> map) {
        final String emailLeader = (String) map.get(Constants.EMAIL_LEADER);
        final WorkApplyInfo workApplyInfo = (WorkApplyInfo) map.get(ApproveConstant.WORK_APPLY_INFO);
        final String titleTemplate = "党建机器人-用章审批流程（审批完成）：{0}";
        final String title = MessageFormat.format(titleTemplate, new String[] {workApplyInfo.getTitle()});
        final String contentTemplate = "您提交的用章申请已完成审批，请点击<a href=\"{0}\">{1}</a>下载审批表。";
        final UriComponentsBuilder urlBuilder = UriComponentsBuilder.fromUriString(talkConfig.getSiteUrl()).
            path("api/chapter/downloadApproveForm").
            queryParam(ApproveConstant.WORK_APPLY_ID_NAME, workApplyInfo.getId());
        final String content = MessageFormat.format(contentTemplate,
                                                    new String[] {urlBuilder.toUriString(), workApplyInfo.getTitle()});
        if (LOGGER.isDebugEnabled()) {
            LOGGER.debug("sendFinishEmailFunction mail title:{},mail receiver:{},mail content:{}", title, workApplyInfo.getCreatorUid(), content);
        }
        notifyService.notifyByEmail(new String[] { StringUtils.isNotBlank(emailLeader) ? emailLeader : workApplyInfo.getCreatorUid() }, title, content);
    }

    /**
     * 发送邮件给印章管理员.
     * 格式
     * 标题：党建机器人-用章审批流程：<工单标题>（流程结束）
     * 内容：
     * 党建机器人-用章审批流程任务工单：<工单标题>
     * 流程已结束。
     *
     * 发起人：张三
     * 发起时间：2022-09-30 10:33
     * @param map 邮件相关参数
     *            key emailLeader: 邮件接收者
     *            key param: uniflow TaskObject
     *            key workApplyInfo:工单实例
     */
    private void sendFinishEmailToManagerFunction(final Map<String, Object> map) {
        final String titleTemplate = "党建机器人-用章审批流程：<{0}>（流程结束）";
        final String contentTemplate = "<a href=\"{0}\">党建机器人-用章审批流程任务工单：<{1}></a>"
            +"<br/>流程已结束。<br/>"
            + "<br/>发起人：{2}"
            + "<br/>发起时间：{3}";
        emailService.sendEmailFunction(titleTemplate, contentTemplate, BizConstant.CHAPTER_APPLY_PROCESS_CODE, talkConfig.getSiteUrl(), map);
    }

    /**
     * 获取印章管理员uid列表.
     * @return 管理员uid
     */
    private Set<String> getManager() {
        return BizCacheUtils.getUserRoleRels(roleService, Constants.ROLE_CHAPTER_ADMIN, redisCacheUtil);
    }

    /**
     * 转交工单.
     * @param taskId 任务id
     * @param info 工单信息
     * @param opinion 意见
     * @param user 当前用户
     * @param transferUser 转交人
     * @throws WorkApplyException 智办工单处理异常
     */
    public void transfer(final String taskId, final WorkApplyInfo info, final String opinion, final LoginUserPojo user, final UserInfo transferUser) throws WorkApplyException {
        try {
            // 验证任务数据是否符合处理标准
            Preconditions.checkArgument(StringUtils.isNotBlank(taskId), WorkApplyInfoService.TASK_ID_BLANK_ERROR_MSG);
            Preconditions.checkArgument(StringUtils.isNotBlank(info.getHandlerUid()) && StringUtils.equals(user.getUserID(), info.getHandlerUid()), "当前用户不是工单处理人！");
            // 设置工单数据
            info.setUpdateTime(LocalDateTime.now().toDate());
            info.setHandlerUid(transferUser.getUserId());
            info.setHandlerName(transferUser.getUserName());
            // 当前节点是直属党委负责人，需要替换支部领导为转交人
            if (WorkStatusEnum.ZSDWFZR == info.getStatus()) {
                info.setPartyLeaderUid(transferUser.getUserId());
                info.setPartyLeaderName(transferUser.getUserName());
            }
            // 更新主工单数据
            this.workApplyInfoMapper.updateWorkApplyInfo(info);
            // 插入审批记录
            this.workApplyInfoMapper.insertWorkApproveOpinion(WorkApplyOperationUtils.buildApproveOpinionWithNodeId(opinion, user, info, ApproveConstant.DEFAULT_TRANSFER_NAME, info.getStatus().getValue()));
            // 处理主工单
            final ResultInfo resultInfo = this.uniFlowService.transferTask(taskId, new UserInfo[]{transferUser}, ApproveConstant.DEFAULT_TRANSFER_NAME, opinion);
            // 验证ucc接口返回结果
            checkUniflowMethodInvokeResult(resultInfo, "转交工单失败：");
            // 操作主工单已办信息，不用操作父工单和子工单
            workDoneStatusInfoService.dealWorkApplyDoneStatus(info, null, null, user);
        } catch (final IllegalArgumentException | NullPointerException e) {
            final String message = String.format("转交工单失败，工单信息[%s]，当前用户[%s]", info, user);
            LOGGER.error(message, e);
            throw new WorkApplyException(message, e);
        }
    }

    /**
     * 验证ucc接口返回结果.
     * @param resultInfo 调用结果对象
     * @param prefix 错误提示语前缀
     */
    private void checkUniflowMethodInvokeResult(final ResultInfo resultInfo, final String prefix) {
        Preconditions.checkNotNull(resultInfo, "调用ucc接口返回结果为空！");
        Preconditions.checkArgument(resultInfo.isResult(), prefix + resultInfo.getInfo());
    }

}
